package br.dcc.ufmg.filtering;

import java.util.LinkedList;
import java.util.List;

import br.dcc.ufmg.domain.Measure;
import br.dcc.ufmg.persistence.ArtifactDAO;
import java.util.Collections;
import java.util.Comparator;

public abstract class ArtifactFilter<T extends Measure> {

	private String system;

	private String expressionFilter;

	private String sortBy;

	private List<T> artifacts;
	
	private int totalArtifactsBeforeFiltering;

	public ArtifactFilter(String system, String expressionFilter, String sortBy) {
		this.system = system;
		this.expressionFilter = expressionFilter;
		artifacts = new LinkedList<T>();
		this.sortBy = sortBy;
	}

	public abstract ArtifactDAO<T> getDAO();

	public List<T> filter() throws Exception {
		List<T> allArtifacts = getDAO().getArtifacts(getSystem());
		setTotalArtifactsBeforeFiltering(allArtifacts.size());
		for (T artifact : allArtifacts) {
			MeasuresEvaluator evaluator = new MeasuresEvaluator();
			for (String metric : artifact.getMeasures().keySet()) {
				evaluator.addMeasures(metric, artifact.getMeasures()
						.get(metric));
			}
			if (evaluator.evaluate(getExpressionFilter())) {
				getArtifacts().add(artifact);
			}
		}
		sortArtifacts();
		return getArtifacts();
	}

	public void sortArtifacts() {
		if (sortBy != null) {
			Collections.sort(getArtifacts(), new Comparator<T>() {
				@Override
				public int compare(T t, T t1) {
					return -1
							* t.getMeasures().get(sortBy)
									.compareTo(t1.getMeasures().get(sortBy));
				}
			});
		}
	}

	public String getSystem() {
		return system;
	}

	public void setSystem(String system) {
		this.system = system;
	}

	public String getExpressionFilter() {
		return expressionFilter;
	}

	public void setExpressionFilter(String expressionFilter) {
		this.expressionFilter = expressionFilter;
	}

	public List<T> getArtifacts() {
		return artifacts;
	}

	public void setMethods(List<T> artifacts) {
		this.artifacts = artifacts;
	}

	public int getTotalArtifactsBeforeFiltering() {
		return totalArtifactsBeforeFiltering;
	}

	public void setTotalArtifactsBeforeFiltering(int totalArtifactsBeforeFiltering) {
		this.totalArtifactsBeforeFiltering = totalArtifactsBeforeFiltering;
	}

}
